﻿/*
 * cumulantmgr.hpp
 *
 *  Created on: 2017年3月27日
 *      Author: work
 */

#ifndef _DM_SCADA_CUMULANTMGR_HPP_
#define _DM_SCADA_CUMULANTMGR_HPP_

#include <dm/export.hpp>

#ifndef DM_API_SCADA
#define DM_API_SCADA DM_API_IMPORT
#endif

#include <dm/scada/scada.hpp>

#include <dm/scada/cumulantinfo.hpp>
#include <dm/scada/timedcumulantmgr.hpp>
#include <dm/scada/cfg.hpp>

#include <iostream>

namespace dm{
namespace scada{

/**
 * 累计量管理器
 * 封装了对系统累计量的访问接口。包括配置信息和实时值。
 */
class DM_API_SCADA CCumulantMgr:protected CScada{
	CCumulantMgr( CScada& scada );
public:
	typedef CScada::cumulant_t rt_t;	//!< 实时值描述

	static CCumulantMgr& ins();

	/**
	 * 获取系统累计量总数
	 * @return
	 */
	inline const int& size()const{
		return m_cfg.size();
	}

	/**
	 * 根据id获取累计量索引号
	 * @param id 累计量id
	 * @return
	 */
	inline index_t indexById( const id_t& id )const{
		return m_cfg.indexOf(id);
	}

	/**
	 * 根据名字获取累计量索引号
	 * @param name 累计量名字
	 * @return
	 */
	inline index_t indexByName( const char* name )const{
		return m_cfg.indexOf(name);
	}

	/**
	 * 通过累计量信息指针获取累计索引
	 * @param info 累计量信息指针
	 * @return
	 */
	inline index_t indexOfInfo( const SCumulantInfo* info )const{
		return m_cfg.indexOf(info);
	}

	index_t indexOfRt( const rt_t* value )const;
	index_t indexOfRt( const volatile rt_t* value )const;

	/**
	 * 获取累计量信息
	 * @param idx 累计量索引号
	 * @return 累计量信息指针
	 * - NULL 未找到
	 */
	inline const SCumulantInfo* info( const index_t& idx )const{
		return m_cfg.at(idx);
	}

	/**
	 * 获取累计量id
	 * @param idx 累计量索引
	 * @return
	 */
	inline id_t id( const index_t& idx )const{
		const SCumulantInfo* p = info(idx);
		return p?p->id:Id_Inv;
	}

	/**
	 * 获取累计量名字字符串
	 * @param idx 累计量索引
	 * @return
	 */
	inline const char* name( const index_t& idx )const{
		const SCumulantInfo* p = info(idx);
		return p?p->name.c_str():NULL;
	}

	/**
	 * 获取累计量描述字符串
	 * @param idx 累计量索引
	 * @return
	 */
	inline const char* desc( const index_t& idx )const{
		const SCumulantInfo* p = info(idx);
		return p?p->desc.c_str():"无效索引";
	}

	bool setDesc( const index_t& idx,const char* str );

	/**
	 * 实际值最小变化范围
	 * @param idx
	 * @return
	 */
	inline SCumulantInfo::delta_t delta( const index_t& idx )const{
		const SCumulantInfo* p = info(idx);
		return p?p->delta: SCumulantInfo::delta_t(0.0);
	}

	bool setDelta( const index_t& idx,SCumulantInfo::delta_t delta );

	/**
	 * 满码值
	 * @param idx
	 * @return
	 */
	inline SCumulantInfo::code_t maxCode( const index_t& idx )const{
		const SCumulantInfo* p = info(idx);
		return p?p->maxCode:0;
	}

	bool setMaxCode( const index_t& idx,SCumulantInfo::code_t code );

	/**
	 * 原始值转换为实际值的系数
	 * @param idx
	 * @return
	 */
	inline SCumulantInfo::coef_t coef( const index_t& idx )const{
		const SCumulantInfo* p = info(idx);
		return p?p->coef: SCumulantInfo::coef_t(0.0);
	}

	bool setCoef( const index_t& idx,SCumulantInfo::coef_t coef );

	bool setFlagSave( const index_t& idx,bool s=true );
	bool setFlagGenTimed( const index_t& idx,bool s=true );
	bool setFlagReportTimed( const index_t& idx,bool s=true );

	index_t deviceIndex( const index_t& index )const;
	const char* deviceDesc( const index_t& index )const;

	/**
	 * 获取实时数据指针
	 * @param idx
	 * @return
	 */
	inline const rt_t* rt( const index_t& idx )const{
		return (idx<0||idx>=size())?NULL:cumulants()+idx;
	}

	/**
	 * 获取实时数据指针
	 * @param idx
	 * @return
	 */
	inline rt_t* rt( const index_t& idx ){
		return (idx<0||idx>=size())?NULL:cumulants()+idx;
	}

	/**
	 * 获取实时数值
	 * @param idx
	 * @return
	 */
	inline CCumulant::value_t rtValue( const index_t& idx ){
		rt_t* p = rt(idx);
		return p?p->getValue().getValue(): CCumulant::value_t(0.0);
	}

	/**
	 * 获取实时原始值
	 * @param idx
	 * @return
	 */
	inline CCumulant::raw_t rtRaw( const index_t& idx ){
		rt_t* p = rt(idx);
		return p?p->getValue().getRaw():0;
	}

	/**
	 * 获取实时数据产生的原因
	 * @param idx
	 * @return
	 */
	inline EDataSource rtDs( const index_t& idx ){
		rt_t* p = rt(idx);
		return p?p->getDataSource():ByUnknow;
	}

	CCumulant::value_t calcValue( const index_t& idx,const CCumulant::raw_t& raw )const;

	/**
	 * 获取实时数据更新的时刻
	 * @param idx
	 * @return
	 */
	inline dm::CTimeStamp rtTs( const index_t& idx ){
		rt_t* p = rt(idx);
		return p?p->getTimeStamp():dm::CTimeStamp();
	}

	bool update( const index_t& idx,const CCumulant::raw_t& raw,const EDataSource& ds,const dm::CTimeStamp& ts=dm::CTimeStamp::cur());
	bool set( const index_t& idx,const CCumulant::raw_t& raw,const EDataSource& ds,const dm::CTimeStamp& ts=dm::CTimeStamp::cur());
	bool gen( const index_t& idx,const CCumulant::raw_t& raw,const dm::CTimeStamp& ts=dm::CTimeStamp::cur());

	void printInfo( const index_t& idx,std::ostream& ostr=std::cout )const;
	void printInfoValue( const index_t& idx,std::ostream& ostr=std::cout );

private:
	TCfg<SCumulantInfo> m_cfg;
};

}
}

#endif /* INCLUDE_DM_SCADA_CUMULANTMGR_HPP_ */
